<?php

App::uses('AppModel', 'Model');

class Ruta extends AppModel {
    /**
     * 				MODEL DATA MEMBERS
     */

    /**
     * Nombre de la tabla en base de datos
     *
     * Tabla relacionada con el modelo en cuestión, este atributo será usado para la generación
     * de consultas a la base de datos
     *
     * @var string
     */
    public $useTable = "rutas";

    /**
     * Clave primaria de la tabla en base de datos
     *
     * Clave primaria que identifica cada registro de la tabla en cuestión
     *
     * @var string
     */
    public $primaryKey = "id_ruta";

    /**
     * Campo de la tabla a usar como etiqueta/descripción
     *
     * Nombre del campo que se mostrara cuando se hacen busquedas del modelo mediante el método finde('list')
     *
     * @var string
     */
    public $displayField = "nombre_ruta";

    /**
     * Nivel de recusividad para la busqueda de entidades relacionadas
     *
     * Este campo sirve para indicar si una consulta debe incluir las entidades
     * relacionadas con el modelo en cuestión:
     * 	-1	->	Solo información de tabla
     * 	0	->	Información de tabla y de belongsTo
     * 	1	->	Información de tabla, de belongsTo y de hasOne-hasMany
     * 	2	->	Información de tabla, de belongsTo, hasOne-hasMany y hasOne-hasMany de los relacionados
     *
     * @var int
     */
    public $recursive = 2;

    /**
     * Nombre del modelo
     *
     * Nombre del modelo que especifica como referirse a el en las consultas, busquedas, ingresos y
     * otras interacciones con la base de datos.
     *
     * @var string
     */
    public $name = "Ruta";

    /**
     * Orden por defecto
     *
     * Orden por defecto para las consultas que se realicen a la base de datos,
     * se pueden incluir varios campos de la base de datos. Si se especifica
     * otro orden, este no se tiene en cuenta.
     *
     * @var array(string)
     */
    public $order = array("Ruta.fecha_creacion_ruta", "Ruta.nombre_ruta");

    /**
     * Relaciones uno a muchos existentes del modelo
     */
    public $hasMany = array(
        "Recorridos" => array(
            "className" => "Recorrido",
            "foreignKey" => "id_ruta",
        ),
        "RutaParada" => array(
            "className" => "RutaParada",
            "foreignKey" => "id_ruta",
        ),
        "WaypointAyuda" => array(
            "className" => "WaypointAyuda",
            "foreignKey" => "id_ruta",
        ),
    );

    /**
     * Validaciones de cada uno de los atributos del modelo
     */
    public $validate = array(
        "id_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => "update",
                "message" => "Id de la ruta no puede estar vacio",
            ),
            "naturalNumber_NoZero" => array(
                "rule" => array("naturalNumber", false),
                "message" => "Id de la ruta debe ser un número entero diferente de cero",
            ),
            "isUnique" => array(
                "rule" => array("isUnique"),
                "message" => "Id de la ruta debe ser único",
            ),
        ),
        "nombre_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => true,
                "message" => "Nombre de la ruta no puede estar vacio",
            ),
            "maxLength" => array(
                "rule" => array("maxLength", 30),
                "message" => "Nombre de la ruta no puede tener más de 30 caracteres",
            ),
        ),
        "descripcion_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => true,
                "message" => "Descripción de la ruta no puede estar vacio",
            ),
            "maxLength" => array(
                "rule" => array("maxLength", 70),
                "message" => "Descripción de la ruta no puede tener más de 70 caracteres",
            ),
        ),
        "estado_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => true,
                "message" => "Estado de la ruta no puede estar vacio",
            ),
            "inList" => array(
                "rule" => array("inList", array('activa', 'inactiva')),
                "message" => "Estado de la ruta debe ser 'activa' o 'inactiva'",
            ),
        ),
        "fecha_creacion_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => "create",
                "message" => "Fecha de creación de la ruta no puede estar vacio",
            ),
            "date" => array(
                "rule" => array("datetime", "ymd"),
                "message" => "Fecha de creación de la ruta debe tener formato yyyy/mm/dd hh:mm",
            ),
        ),
        "fecha_modificacion_ruta" => array(
            "notEmpty" => array(
                "rule" => "notEmpty",
                "allowEmpty" => false,
                "required" => true,
                "message" => "Fecha de modificación de la ruta no puede estar vacio",
            ),
            "date" => array(
                "rule" => array("datetime", "ymd"),
                "message" => "Fecha de modificación de la ruta debe tener formato yyyy/mm/dd hh:mm",
            ),
        ),
    );

    /**
     * 				DATA VALIDATION METHODS
     */
    /**
     * 				MODEL CALLBACKS METHODS
     */
    // public function beforeFind(array $queryData) {
    // }
    // public function afterFind(array $results, boolean $primary = false) {
    // }
    // public function beforeValidate(array $options = array()) {
    // }
    // public function beforeSave(array $options = array()) {
    // }
    // public function afterSave(boolean $created) {
    // }
    // public function beforeDelete(boolean $cascade = true) {
    // }
    // public function afterDelete() {
    // }

    /**
     * 				MODEL METHODS
     */
    public function findActivas() {
        return $this->find('all', array(
                    'conditions' => array("Ruta.estado_ruta" => "activa"),
                    'recursive' => 2,
        ));
    }

    /**
     * Descripcion corta metodo.
     *
     * Descripción larga metodo
     *
     * @param array() $data parametro que sirve para..
     * @param boolean $validate parametro que sirve para..
     * @param boolean $fieldList parametro que sirve para..
     * @return boolean true en caso de exito, false en otro caso
     */
    public function save($data = null, $validate = true, $fieldList = array()) {
        $this->set($data);
        if (!isset($data["Ruta"]['id_ruta'])) {
            $this->set(array(
                'fecha_creacion_ruta' => date("Y/m/j H:i:s"),
                'estado_ruta' => "activa",
            ));
        }
        $this->set(array(
            'fecha_modificacion_ruta' => date("Y/m/j H:i:s")
        ));
        return parent::save($this->data, $validate, $fieldList);
    }

    /**
     * Descripcion corta metodo.
     *
     * Descripción larga metodo
     *
     * @param int $id parametro que sirve para..
     * @param boolean $cascade parametro que sirve para..
     * @return boolean true en caso de exito, false en otro caso
     */
    public function delete($id = null, $cascade = true) {
        $ruta = $this->find('first', array(
            'conditions' => array('Ruta.id_ruta' => $id),
            'recursive' => 1,
        ));

        $hasChilds = false;
        $hasParadas = false;
        foreach ($ruta as $child_model => $i) {
            if (!in_array($child_model, array("Ruta", "RutaParada", "WaypointAyuda")) && sizeof($ruta[$child_model]) != 0) {
                $hasChilds = true;
                break;
            }
        }

        if (!$hasChilds) {
            $db = $this->getDataSource();
            $db->begin();
            $deleteRutaParada = true;
            foreach ($ruta['RutaParada'] as $i => $detallesRutaParada) {
                $deleteRutaParada = $this->RutaParada->delete($detallesRutaParada['id_rutas_paradas']);
                if (!$deleteRutaParada) {
                    $db->rollback();
                    return false;
                }
            }
            foreach ($ruta['WaypointAyuda'] as $i => $detallesWaypointAyuda) {
                $deleteWaypointAyuda = $this->WaypointAyuda->delete($detallesWaypointAyuda['id_waypoint_ayuda']);
                if (!$deleteWaypointAyuda) {
                    $db->rollback();
                    return false;
                }
            }

            $deleteRuta = parent::delete($id, $cascade);
            if ($deleteRuta) {
                $db->commit();
                return true;
            } else {
                $db->rollback();
                return false;
            }
        } else {
            $ruta["Ruta"]["estado_ruta"] = "inactiva";
            return $this->save($ruta);
        }
    }

    /**
     * Guarda una ruta y las rutas_paradas
     *
     * Se almacenan los datos basicos de la ruta, se borran las rutas_paradas
     * de la ruta en cuestión y se almacenan las nuevas que el usuario haya ingresado
     * se validan las condidiciones necesarias y se almacenan las rutas paradas.
     * De haber algun error en el procedimiento anteriormente descrito se revierten
     * todas las operaciones realizadas en BD.
     *
     * @param array $data el request enviado con toda la información de rutas y rutas_paradas
     * @return boolean true en caso de exito, false en otro caso
     */
    public function guardarRutasParadas($data = null, $validate = true, $fieldList = array()) {
        $db = $this->getDataSource();
        $db->begin();
        if ($this->save($data, $validate, $fieldList)) {
            $this->RutaParada->deleteAll(array('RutaParada.id_ruta' => $this->id));
            $rutaspvalidos = true;
            foreach ($data['RutaParada'] as $i => $rutaparada) {
                $rutaparada['id_ruta'] = $this->id;
                $this->RutaParada->create();
                if (!$this->RutaParada->save($rutaparada)) {
                    $rutaspvalidos = false;
                }
            }
            if (!$rutaspvalidos) {
                $db->rollback();
                return false;
            } else {

                if ($this->validacionParadaInicioFin($data)) {
                    if ($this->validacionParadasConsecutivas($data)) {
                        if ($this->guardarWaypointsAyuda($data, $this->id)) {
                            $db->commit();
                            return true;
                        } else {
                            $db->rollback();
                            return false;
                        }
                    } else {
                        $db->rollback();
                        throw new MissingBehaviorException(__('misma_parada_consecutiva'));
                    }
                } else {
                    $db->rollback();
                    throw new MissingBehaviorException(__('parada_origen_destino_requerida'));
                }
            }
        } else {
            $db->rollback();
            return false;
        }
    }

    /**
     * Valida que se tenga una parada de origen y destino
     *
     * Se recorren las RutasParadas y se verifica que haya una de origen y destino
     *
     * @param array $data el request enviado con toda la información de rutas y rutas_paradas
     * @return boolean true en caso de exito, false en otro caso
     */
    public function validacionParadaInicioFin($data = null) {
        if (!is_null($data)) {
            $inicio = false;
            $destino = false;
            foreach ($data['RutaParada'] as $i => $rutaparada) {
                if ($rutaparada['tipo_parada'] == 'origen') {
                    $inicio = true;
                }
                if ($rutaparada['tipo_parada'] == 'destino') {
                    $destino = true;
                }
                if ($inicio && $destino) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Valida que no se tenga la misma parada de forma consecutiva
     *
     * Se recorren las RutasParada se ordenan en el orden_ruta, luego se
     * verifica que no se tenga la misma parada de forma consecutiva.
     *
     * @param array $data el request enviado con toda la información de rutas y rutas_paradas
     * @return boolean true en caso de exito, false en otro caso
     */
    public function validacionParadasConsecutivas($data = null) {
        if (!is_null($data)) {
            $rutasParadasOrdenedas = Array();
            for ($j = 1; $j <= sizeof($data['RutaParada']); $j++) {
                foreach ($data['RutaParada'] as $i => $rutaparada) {
                    if ($rutaparada['orden_ruta'] == $j) {
                        $rutasParadasOrdenedas[] = $rutaparada;
                    }
                }
            }
            foreach ($rutasParadasOrdenedas as $z => $rutaparada2) {
                if ($z != 0) {
                    if ($rutasParadasOrdenedas[$z - 1]['id_parada'] == $rutaparada2['id_parada']) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * Guarda los waypoints de ayuda
     *
     * Se almacenan los datos relacionados con los waypoints de ayuda asociados a una ruta en
     * especifica, estos waypoints no son paradas de miBus, si no que son elementos graficos,
     * que tienen como objetivo modificar el curso de la ruta, para que si represente el
     * recorrido que existe en la vida real.
     *
     * @param array $data el request enviado con toda la información de rutas y rutas_paradas y waypoints
     * @return boolean true en caso de exito, false en otro caso
     */
    public function guardarWaypointsAyuda($data = null, $id = null) {
        if ($id == null) {
            return false;
        }
        $waArray = [];
        $waCounter = 0;
        foreach ($data as $i => $elemento) {
            if (is_string($elemento) && strpos($elemento, "wa") == 0) {
                $waArray[] = explode("|", $elemento);
                $waCounter++;
            }
        }
        $wsa = $this->WaypointAyuda->find('all', array(
            'conditions' => array('WaypointAyuda.id_ruta' => $id),
            'recursive' => -1,
        ));

        foreach ($wsa as $i => $ws) {
            $this->WaypointAyuda->delete($ws['WaypointAyuda']['id_waypoint_ayuda']);
        }

        foreach ($waArray as $wa) {
            $this->WaypointAyuda->create();
            $nWA = [];
            $nWA['latitud'] = $wa[0];
            $nWA['longitud'] = $wa[1];
            $nWA['id_waypoint_parada'] = $wa[2];
            $nWA['id_ruta'] = $id;
            $this->WaypointAyuda->save($nWA);
        }

        return true;
    }

}
